﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Configuration;
using System.Linq;
using FriendsNearby.Services;
using FriendsNearby.Services.Entities;
using FriendsNearby.Services.Tests.Mocks;
using InSTEDD.Labs.Geo;
using InSTEDD.Labs.Geo.GeoCoding.Google;
using NUnit.Framework;
using Twitter;
using Twitter.Tests;

namespace FriendsNearbyBot.Tests
{
	[TestFixture]
    public class UpdateLocationProcessorFixture : TestBase
	{
		[Test]
		public void ShouldSendAlertIfTwitterNotMapped()
		{
			IServiceProvider services = CreateServices();
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtesta");
			bot.SetBuddy(user);
			user.SetBuddy(bot);
            UpdateLocationProcessor processor = new UpdateLocationProcessor(services, CreateMessageBuilder());

            processor.Process(bot, CreateMessage("at 33*-53", user.ScreenName, bot.ScreenName));

			Assert.AreEqual(1, user.Messages.GetAll().Count());
			Assert.AreEqual(
				String.Format(Properties.Resources.TwitterNotMapped, user.ScreenName),
				user.Messages.GetAll().First().Text);
		}

		[Test]
		public void ShouldSendAlertIfInvalidLatLong()
		{
			IServiceProvider services = CreateServices();
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtesta");
			bot.SetBuddy(user);
			user.SetBuddy(bot);
            UpdateLocationProcessor processor = new UpdateLocationProcessor(services, CreateMessageBuilder());

			services.GetService<IUsersService, MockUsersService>().SetUserPreferences(
				new UserPreference
				{
					FacebookUserId = "fnbtesta",
					TwitterScreenName = "fnbtesta"
				});
            
            processor.Process(bot, CreateMessage("at 99999*asdfg", user.ScreenName, bot.ScreenName));

			Assert.AreEqual(1, user.Messages.GetAll().Count());
			Assert.AreEqual(
				string.Format(Properties.Resources.InvalidLocation, "99999*asdfg"), 
				user.Messages.GetAll().First().Text);
		}

		[Test]
        [Ignore("Country Border Config")] // TODO fix configuration
		public void ShouldSetCurrentLocation()
		{
			IServiceProvider services = CreateServices();
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtesta");
			bot.SetBuddy(user);
			user.SetBuddy(bot);
            UpdateLocationProcessor processor = new UpdateLocationProcessor(services, CreateMessageBuilder());

			services.GetService<IUsersService, MockUsersService>().SetUserPreferences(
				new UserPreference
				{
					FacebookUserId = "fnbtesta",
					TwitterScreenName = "fnbtesta"
				});

            processor.Process(bot, CreateMessage("at 33*44 nack", user.ScreenName, bot.ScreenName));

			UserInfo info = services.GetService<ILocationService>().GetCurrentLocation(user.ScreenName);

			Assert.AreEqual(33, info.Location.Lat);
			Assert.AreEqual(44, info.Location.Long);
			// Shouldn't have received any messages back.
			Assert.AreEqual(0, user.Messages.GetAll().Count());
		}

		[Test]
		public void ShouldSendLocationAck()
		{
			IServiceProvider services = CreateServices();
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtesta");
			bot.SetBuddy(user);
			user.SetBuddy(bot);
            UpdateLocationProcessor processor = new UpdateLocationProcessor(services, CreateMessageBuilder());

			services.GetService<IUsersService, MockUsersService>().SetUserPreferences(
				new UserPreference
				{
					FacebookUserId = "fnbtesta",
					TwitterScreenName = "fnbtesta"
				});
			
            processor.Process(bot, CreateMessage("at 33*44", user.ScreenName, bot.ScreenName));

			Assert.AreEqual(1, user.Messages.GetAll().Count());
			Assert.That(user.Messages.GetAll().First().Text.StartsWith("We got your location update"));
			Console.WriteLine(user.Messages.GetAll().First().Text);
		}

		[Test]
		public void ShouldUpdateLocationFromAddress()
		{
			IServiceProvider services = CreateServices();
			MemoryBotClient bot = new MemoryBotClient("fnb");
			MemoryBotClient user = new MemoryBotClient("fnbtesta");
			bot.SetBuddy(user);
			user.SetBuddy(bot);
            UpdateLocationProcessor processor = new UpdateLocationProcessor(services, CreateMessageBuilder());

			services.GetService<IUsersService, MockUsersService>().SetUserPreferences(
				new UserPreference
				{
					FacebookUserId = "fnbtesta",
					TwitterScreenName = "fnbtesta"
				});

			CopyGoogleMapsKey();

            processor.Process(bot, CreateMessage("at 400 Hamilton Ave, Suite 120, Palo Alto, CA", user.ScreenName, bot.ScreenName));

			UserInfo info = services.GetService<ILocationService>().GetCurrentLocation(user.ScreenName);

			Assert.AreEqual(37.446345, info.Location.Lat);
			Assert.AreEqual(-122.159078, info.Location.Long);

			Assert.AreEqual(1, user.Messages.GetAll().Count());
			Assert.That(user.Messages.GetAll().First().Text.StartsWith("We got your location update"));
			//Assert.That(user.Messages.GetAll().First().Text.Contains(""));
			Console.WriteLine(user.Messages.GetAll().First().Text);
		}

		[Test]
		public void ShouldGeoCodeInSTEDDLocation()
		{
			string location = "400 Hamilton Ave, Suite 120, Palo Alto, CA";
			string key = "ABQIAAAALR_Ja6qu5mcjRXi1RFyughT2yXp_ZAY8_ufC3CFXhHIE1NvwkxS_nVo_W373WxAcBJapCmu_zDRx7A";

			GoogleGeoCoder google = new GoogleGeoCoder();
			google.Initialize(key);

			LatLong loc = google.GetLatLongFromPostalAddress(location);

			Assert.IsNotNull(loc);
			Assert.AreEqual(37.446345, loc.Lat);
			Assert.AreEqual(-122.159078, loc.Long);
		}

		private void CopyGoogleMapsKey()
		{
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap{ ExeConfigFilename = "App.config" };
			Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            string googleKey = configuration.AppSettings.Settings["GoogleMapsAPIKey"].Value;
			Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
			config.AppSettings.Settings.Add(
                "GoogleMapsAPIKey", googleKey);
			config.Save();
		}

		private IServiceProvider CreateServices()
		{
			ServiceContainer container = new ServiceContainer();
			container.AddService<ILocationService>(new MockLocationService());
			container.AddService<IUsersService>(new MockUsersService());
			container.AddService<ISocialNetworkService>(new MockSocialNetworkService());
			container.AddService<IPeopleNearbyService>(new MockPeopleNearby());

			return container;
		}        
	}
}
